<template>
    <div class="weather-page">
        <div class="toolbar">
            <el-input v-model="keyword" placeholder="搜索城市（拼音/中文）" clearable class="search-input" @input="filterCities" />
            <el-button type="primary" :loading="loading" @click="refreshAll">刷新</el-button>
        </div>

        <el-row :gutter="16">
            <el-col v-for="city in filteredCities" :key="city.name" :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
                <el-card class="city-card" shadow="hover">
                    <div class="city-header">
                        <div class="city-name">{{ city.name }}</div>
                        <div class="city-sub">{{ city.province }}</div>
                    </div>

                    <div class="current" v-if="city.weather">
                        <div class="temp">{{ Math.round(city.weather.current.temp) }}°C</div>
                        <div class="desc">
                            <span class="icon">{{ city.weather.current.icon }}</span>
                            <span>{{ city.weather.current.text }}</span>
                        </div>
                        <div class="meta">
                            <span>风速 {{ city.weather.current.wind }} m/s</span>
                            <span>湿度 {{ city.weather.current.humidity }}%</span>
                        </div>
                    </div>
                    <div class="current" v-else>
                        <el-skeleton animated :rows="3" />
                    </div>

                    <div class="forecast" v-if="city.weather">
                        <div v-for="(d, idx) in city.weather.daily" :key="idx" class="day">
                            <span class="d">{{ d.date }}</span>
                            <span class="i">{{ d.icon }}</span>
                            <span class="t">{{ Math.round(d.tmin) }}~{{ Math.round(d.tmax) }}°C</span>
                        </div>
                    </div>
                </el-card>
            </el-col>
        </el-row>
    </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';

type City = {
    name: string;
    province: string;
    latitude: number;
    longitude: number;
    pinyin: string;
    weather?: {
        current: { temp: number; text: string; icon: string; wind: number; humidity: number };
        daily: Array<{ date: string; tmin: number; tmax: number; icon: string; text: string }>;
    };
};

const allCities = ref<City[]>([
    { name: '北京', province: '北京', latitude: 39.9042, longitude: 116.4074, pinyin: 'beijing' },
    { name: '上海', province: '上海', latitude: 31.2304, longitude: 121.4737, pinyin: 'shanghai' },
    { name: '广州', province: '广东', latitude: 23.1291, longitude: 113.2644, pinyin: 'guangzhou' },
    { name: '深圳', province: '广东', latitude: 22.5431, longitude: 114.0579, pinyin: 'shenzhen' },
    { name: '杭州', province: '浙江', latitude: 30.2741, longitude: 120.1551, pinyin: 'hangzhou' },
    { name: '南京', province: '江苏', latitude: 32.0603, longitude: 118.7969, pinyin: 'nanjing' },
    { name: '成都', province: '四川', latitude: 30.5728, longitude: 104.0668, pinyin: 'chengdu' },
    { name: '重庆', province: '重庆', latitude: 29.5630, longitude: 106.5516, pinyin: 'chongqing' },
    { name: '武汉', province: '湖北', latitude: 30.5928, longitude: 114.3055, pinyin: 'wuhan' },
    { name: '西安', province: '陕西', latitude: 34.3416, longitude: 108.9398, pinyin: 'xian' },
    { name: '天津', province: '天津', latitude: 39.3434, longitude: 117.3616, pinyin: 'tianjin' },
    { name: '青岛', province: '山东', latitude: 36.0671, longitude: 120.3826, pinyin: 'qingdao' },
    { name: '大连', province: '辽宁', latitude: 38.9140, longitude: 121.6147, pinyin: 'dalian' },
    { name: '沈阳', province: '辽宁', latitude: 41.8057, longitude: 123.4315, pinyin: 'shenyang' },
    { name: '哈尔滨', province: '黑龙江', latitude: 45.8038, longitude: 126.5350, pinyin: 'haerbin' },
    { name: '郑州', province: '河南', latitude: 34.7473, longitude: 113.6249, pinyin: 'zhengzhou' },
    { name: '长沙', province: '湖南', latitude: 28.2278, longitude: 112.9389, pinyin: 'changsha' },
    { name: '南昌', province: '江西', latitude: 28.6820, longitude: 115.8579, pinyin: 'nanchang' },
    { name: '合肥', province: '安徽', latitude: 31.8206, longitude: 117.2290, pinyin: 'hefei' },
    { name: '厦门', province: '福建', latitude: 24.4798, longitude: 118.0894, pinyin: 'xiamen' },
    { name: '福州', province: '福建', latitude: 26.0745, longitude: 119.2965, pinyin: 'fuzhou' },
    { name: '昆明', province: '云南', latitude: 24.8801, longitude: 102.8329, pinyin: 'kunming' },
    { name: '贵阳', province: '贵州', latitude: 26.6470, longitude: 106.6302, pinyin: 'guiyang' },
    { name: '南宁', province: '广西', latitude: 22.8170, longitude: 108.3669, pinyin: 'nanning' },
    { name: '海口', province: '海南', latitude: 20.0440, longitude: 110.1999, pinyin: 'haikou' },
    { name: '拉萨', province: '西藏', latitude: 29.6520, longitude: 91.1721, pinyin: 'lasa' },
    { name: '乌鲁木齐', province: '新疆', latitude: 43.8256, longitude: 87.6168, pinyin: 'wulumuqi' },
    { name: '呼和浩特', province: '内蒙古', latitude: 40.8426, longitude: 111.7492, pinyin: 'huhehaote' },
    { name: '兰州', province: '甘肃', latitude: 36.0611, longitude: 103.8343, pinyin: 'lanzhou' },
    { name: '银川', province: '宁夏', latitude: 38.4872, longitude: 106.2309, pinyin: 'yinchuan' },
    { name: '西宁', province: '青海', latitude: 36.6171, longitude: 101.7782, pinyin: 'xining' },
]);

const filteredCities = ref<City[]>([]);
const keyword = ref('');
const loading = ref(false);

const filterCities = () => {
    const k = keyword.value.trim().toLowerCase();
    if (!k) {
        filteredCities.value = allCities.value;
        return;
    }
    filteredCities.value = allCities.value.filter(c => c.name.includes(k) || c.pinyin.includes(k));
};

const codeMap: Record<number, { text: string; icon: string }> = {
    0: { text: '晴', icon: '☀️' },
    1: { text: '多云', icon: '🌤️' },
    2: { text: '多云', icon: '⛅' },
    3: { text: '阴', icon: '☁️' },
    45: { text: '雾', icon: '🌫️' },
    48: { text: '雾', icon: '🌫️' },
    51: { text: '毛毛雨', icon: '🌦️' },
    53: { text: '毛毛雨', icon: '🌦️' },
    55: { text: '毛毛雨', icon: '🌦️' },
    56: { text: '冻毛毛雨', icon: '🌧️' },
    57: { text: '冻毛毛雨', icon: '🌧️' },
    61: { text: '小雨', icon: '🌧️' },
    63: { text: '中雨', icon: '🌧️' },
    65: { text: '大雨', icon: '🌧️' },
    66: { text: '冻雨', icon: '🌧️' },
    67: { text: '冻雨', icon: '🌧️' },
    71: { text: '小雪', icon: '🌨️' },
    73: { text: '中雪', icon: '🌨️' },
    75: { text: '大雪', icon: '🌨️' },
    77: { text: '雪粒', icon: '🌨️' },
    80: { text: '阵雨', icon: '🌦️' },
    81: { text: '阵雨', icon: '🌦️' },
    82: { text: '强阵雨', icon: '🌧️' },
    85: { text: '阵雪', icon: '🌨️' },
    86: { text: '强阵雪', icon: '🌨️' },
    95: { text: '雷雨', icon: '⛈️' },
    96: { text: '雷雨伴冰雹', icon: '⛈️' },
    99: { text: '强雷雨伴冰雹', icon: '⛈️' },
};

const mapCode = (code: number) => codeMap[code] || { text: '未知', icon: '❓' };

const fetchCityWeather = async (city: City) => {
    const url = `https://api.open-meteo.com/v1/forecast?latitude=${city.latitude}&longitude=${city.longitude}&current_weather=true&daily=weathercode,temperature_2m_max,temperature_2m_min&timezone=Asia/Shanghai`;
    const res = await fetch(url);
    if (!res.ok) throw new Error(city.name + ' 天气获取失败');
    const data = await res.json();
    const currentCode = Number(data.current_weather?.weathercode ?? 0);
    const current = {
        temp: Number(data.current_weather?.temperature ?? 0),
        text: mapCode(currentCode).text,
        icon: mapCode(currentCode).icon,
        wind: Number(data.current_weather?.windspeed ?? 0),
        humidity: Number(data.hourly?.relativehumidity_2m?.[0] ?? 0),
    };
    const dailyDates: string[] = data.daily?.time || [];
    const dailyMin: number[] = data.daily?.temperature_2m_min || [];
    const dailyMax: number[] = data.daily?.temperature_2m_max || [];
    const dailyCode: number[] = data.daily?.weathercode || [];
    const daily = dailyDates.map((d: string, i: number) => ({
        date: d.slice(5),
        tmin: Number(dailyMin[i] ?? 0),
        tmax: Number(dailyMax[i] ?? 0),
        icon: mapCode(Number(dailyCode[i] ?? 0)).icon,
        text: mapCode(Number(dailyCode[i] ?? 0)).text,
    })).slice(0, 7);
    city.weather = { current, daily };
};

// 已声明于上方

const refreshAll = async () => {
    loading.value = true;
    try {
        await Promise.all(filteredCities.value.map(c => fetchCityWeather(c)));
        ElMessage.success('已更新全国天气');
    } catch (e: any) {
        ElMessage.error(e?.message || '获取天气失败');
    } finally {
        loading.value = false;
    }
};

onMounted(async () => {
    filteredCities.value = allCities.value;
    await refreshAll();
});
</script>

<style scoped>
.weather-page {
    padding: 16px;
}

.toolbar {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 16px;
}

.search-input {
    max-width: 260px;
}

.city-card {
    margin-bottom: 16px;
}

.city-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 8px;
}

.city-name {
    font-size: 18px;
    font-weight: 600;
}

.city-sub {
    color: #909399;
    font-size: 12px;
}

.current {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    grid-column-gap: 8px;
    grid-row-gap: 4px;
    align-items: center;
    margin-bottom: 8px;
}

.temp {
    grid-row: span 2;
    font-size: 28px;
    font-weight: 700;
}

.desc {
    display: flex;
    gap: 6px;
    align-items: center;
}

.meta {
    color: #606266;
    font-size: 12px;
    display: flex;
    gap: 10px;
}

.forecast {
    border-top: 1px dashed #ebeef5;
    padding-top: 8px;
}

.day {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 12px;
    color: #606266;
}

.day + .day {
    margin-top: 4px;
}

.d { width: 64px; }
.i { width: 24px; text-align: center; }
.t { width: 92px; text-align: right; }
</style>